#include "Filter.h"
#include <atlconv.h>
#include "../Exception.h"

// TODO: HACKY.... needed a source file to implement this.. too lazy to create a new one :P
// including atlconv.h before d3d9.h causes the d3d9 api to break
Exception::Exception(const std::string& message) 
{
	USES_CONVERSION;
	this->message = A2W(message.c_str());

}

Filter::Filter( IDirect3DDevice9* device, IShader* shader ) : device(device), shader(shader)
{
	screenMask.Create(device, 0, 0, 1, 1);
}


void Filter::Render( const std::string& technique, int downsampling)
{
	float coords = 1.0f/(float)downsampling;
	screenMask.Remove();
	screenMask.Create(device, 0, 0, coords, coords);

	screenMask.BeginRender(device);

	if(technique == "")
		shader->Begin();
	else
		shader->Begin(technique);

	unsigned int passCount = shader->get_PassCount();
	for(unsigned int currentPass=0; currentPass<passCount; ++currentPass)
	{
		RenderPassReturnValue::Enumeration returnValue;
		do
		{
			returnValue = shader->BeginPass(currentPass);
			if (returnValue != RenderPassReturnValue::RenderAndCallNot)
				screenMask.Render(device);
		} while(returnValue == RenderPassReturnValue::RenderAndCallAgain);
		shader->EndPass(); 
	}
	shader->End();
}



FilterManager::FilterManager( IDirect3DDevice9* device, const std::wstring& pluginPath ) : device(device)
{
	USES_CONVERSION;
	this->pluginPath = W2A(pluginPath.c_str());
	shaderSystem = new ShaderSystem(device);
}


FilterManager::~FilterManager()
{
	delete shaderSystem;
}


Filter* FilterManager::LoadFilter( const std::string& filename )
{
	std::string path = pluginPath+filename;
	IShader* shader = shaderSystem->LoadShader(filename, path);
	return new Filter(device, shader);
}


void FilterManager::AddParameter( const std::string& name, IDirect3DTexture9* texture )
{
	shaderSystem->AddSemanticHandler(new TextureSemanticHandler(name, texture));
}


void FilterManager::AddParameter( const std::string& name, float* value)
{
	shaderSystem->AddSemanticHandler(new FloatSemanticHandler(name, value));
}


void FilterManager::AddParameter( const std::string& name, D3DXVECTOR4* value)
{
	shaderSystem->AddSemanticHandler(new Float4SemanticHandler(name, value));
}


void FilterManager::ClearParameters()
{
	shaderSystem->ClearSemanticHandler();
}
